// FILE: Chip8CPU.h by Richard Hughes 28/04/2012
//
// DESC: Defines the Chip8 CPU

#ifndef __chip8cpu_h__
#define __chip8cpu_h__

// INCLUDES
#include "ICPU.h"
#include "IInterupt.h"

// NAMESPACES
namespace Emulator
{
namespace Chip8
{

class Chip8Emulator;

/*************************************************************/
//
// CLASS: Chip8CPU
//
// DESC: Defines the Chip8 CPU
//
/*************************************************************/

class Chip8CPU
{
private:

	Chip8Emulator* _emulator;

	uint8_t Vx[0xF]; // 16 of them V0 - VF
	uint16_t I;

	uint8_t Timer;
	uint8_t Sound;

	address PC;
	uint8_t SP;

	uint16_t Stack[16];

	long _lastFrameTime;
	long _currentFrameTime;
public:

	Chip8CPU();
	~Chip8CPU();

	inline void SetEmulator(Chip8Emulator* emu) { this->_emulator = emu; }

	uint16_t Tick(IRAM* ram);

	void Do0x0(uint16_t op);
	void Do0x1(uint16_t op);
	void Do0x2(uint16_t op);
	void Do0x3(uint16_t op);
	void Do0x4(uint16_t op);
	void Do0x5(uint16_t op);
	void Do0x6(uint16_t op);
	void Do0x7(uint16_t op);
	void Do0x8(uint16_t op);
	void Do0x9(uint16_t op);
	void Do0xA(uint16_t op);
	void Do0xB(uint16_t op);
	void Do0xC(uint16_t op);
	void Do0xD(uint16_t op, IRAM* ram);
	void Do0xE(uint16_t op);
	void Do0xF(uint16_t op, IRAM* ram);

	void ActionInterupt(IInterupt* interupt);

	void HandleTimer();
	void HandleSound();

	uint8_t const GetVF(uint8_t index) const { return this->Vx[index]; }

	uint16_t const GetI() const { return this->I; }

	uint8_t const GetTimer() const { return this->Timer; }
	uint8_t const GetSound() const { return this->Sound; }

	address const GetPC() const { return this->PC; }
	void SetPC(address add) { this->PC = add; }

	uint8_t const GetSP() const { return this->SP; }

	uint16_t* const GetStack() const { return (uint16_t* const)this->Stack; }

}; // Chip8CPU

} // Chip8
} // Emulator

#endif // __chip8cpu_h__

// EOF: Chip8CPU.h